﻿

namespace TouchPoint.IO
{
    using System;
    using Windows.Storage;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading.Tasks;

    /// <summary>
    /// 
    /// </summary>
    public sealed class TpmlTokenizer
    {

        #region ContentStream

        // // .+ crlf
        // /* */
        // <!-- -->
        enum CommentType
        {
            Empty,
            CStyleSingleLine,
            CStyleMultiLine,
            PrepareStartXMLComment,     // <!
            StartXmlComment,            // -- 
            PrepareCloseXMLComment,     // --
            CloseXMLComment             // ->
        }

        public sealed class ContentStream
        {
            string _input;
            int    _position;

            public ContentStream(string str)
            {
                if (string.IsNullOrEmpty(str)) {
                    throw new NullReferenceException("字符流不能为空");
                }

                CommentType type = CommentType.Empty;
                
                // Parse Comment
                StringBuilder builder = new StringBuilder();
                char lastCh = char.MinValue;

                foreach(var ch in str) {
                    switch (type) {
                        case CommentType.Empty:
                            if(lastCh=='/' && ch == '/') {
                                type = CommentType.CStyleSingleLine;
                            }else if(lastCh == '/' && ch == '*') {
                                type = CommentType.CStyleMultiLine;
                            }else if(lastCh == '<' && ch == '!'){
                                type = CommentType.PrepareStartXMLComment;
                            }                            
                            break;
                        case CommentType.CStyleSingleLine:
                            if (ch == '\n') {
                                type = CommentType.Empty;
                            }
                            break;
                        case CommentType.CStyleMultiLine:
                            if(lastCh=='*' && ch == '/') {
                                type = CommentType.Empty;
                            }
                            break;
                        case CommentType.PrepareStartXMLComment:
                            if(lastCh == '-' && ch == '-') {
                                type = CommentType.StartXmlComment;
                            }break;
                        case CommentType.StartXmlComment:
                            if(lastCh=='-' && ch == '-') {
                                type = CommentType.PrepareCloseXMLComment;
                            }break;
                        case CommentType.PrepareCloseXMLComment:
                            if(lastCh=='-' && ch == '>') {
                                type = CommentType.Empty;
                            }
                            else {
                                type = CommentType.StartXmlComment;
                            }
                            break;
                        default:
                            builder.Append(ch);
                            break;
                    }
                    lastCh = ch;
                }

                _input = builder.ToString();
            }

            /// <summary>
            /// 返回当前位置的字符
            /// </summary>
            public char Current {
                get {
                    return _input[_position];
                }
            }

            /// <summary>
            /// 尝试将当前字符流提升一位
            /// </summary>
            /// <returns>如果成功则返回true</returns>
            public bool MovePrev()
            {
                if(_position > 0) {
                    _position--;
                    return true;
                }
                return false;
            }

            /// <summary>
            /// 尝试将当前流向下下降一位
            /// </summary>
            /// <returns>如果成功则返回true</returns>
            public bool MoveNext()
            {
                if (_position < _input.Length) {
                    _position++;
                    return true;
                }
                return false;
            }

            /// <summary>
            /// 获取当前字符流是否到达末端
            /// </summary>
            public bool EndOfStream {
                get {
                    return _position == _input.Length;
                }
            }

            /// <summary>
            /// 当前的内容
            /// </summary>
            public string Content {
                get {
                    return _input;
                }
            }

            /// <summary>
            /// 返回当前位置的字符
            /// </summary>
            /// <returns>返回当前位置的字符</returns>
            public override string ToString()
            {
                return Current.ToString();
            }
        }

        #endregion

        #region 状态机

        enum TpmlState:int
        {
            Empty,                              // 起始状态
            StartElementTag,                    // 第一个XML左尖括号
             
            ElementName
        }

        //---------------------------------------------------------------------------------------------------
        //  使用单独的类维护状态机状态
        //---------------------------------------------------------------------------------------------------

        sealed class DFA
        {
            bool        _stateChanged;
            TpmlState   _state;

            public void Put(char c)
            {

            }

            /// <summary>
            /// 指示当前操作是否导致状态移动
            /// </summary>
            public bool StateChanged {
                get {
                    return _stateChanged;
                }
            }

            /// <summary>
            /// 
            /// </summary>
            public TpmlState State {
                get {
                    return _state;
                }
            }
        }

        #endregion

        ContentStream    _input;
        Queue<TpmlToken> _token;

        #region Constructor

        private TpmlTokenizer(string tpml)
        {
            _input = new ContentStream(tpml);
            _token = new Queue<TpmlToken>();
        }

        #endregion

        #region Load Method

        /// <summary>
        /// LoadFrom
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        async public Task<TpmlTokenizer> Load(StorageFile file)
        {
            var tpml = await FileIO.ReadTextAsync(file);
            return Load(tpml);
        }

        public TpmlTokenizer Load(string tpml)
        {
            return new TpmlTokenizer(tpml);
        }

        #endregion

        #region Public Method

        public void Parse()
        {

        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public TpmlToken ReadNextToken()
        {
            if(_token.Count > 0) {
                return _token.Dequeue();
            }
            return null;
        }

        #endregion


    }
}
